import { Sprite } from '../engine/nodes/sprite.js';
import { mat4, vec3 } from '../engine/gl-matrix/index.js'
import { Bullet } from './bullet.js'
import { databus } from './databus.js'
import { music } from './music.js'
import { BoxCollider2D } from '../engine/core/boxCollider2D.js'

export class Player extends Sprite {
    constructor() {
        super({ url: "images/hero.png" });

        this.name = "player";
        this.translation = vec3.fromValues(0.0, -0.8, 0.0);
        this.scale = vec3.fromValues(0.186 * 0.7, 0.130 * 0.7, 1.0);

        this._minX = -databus.rightX + this.scale[0];
        this._maxX = databus.rightX - this.scale[0];
        this._minY = -databus.topY + this.scale[1];
        this._maxY = databus.topY - this.scale[1];

        this.material.renderOrder = 2;

        this.fireCooldown = databus.fireCooldown;
        this._time = 0;
        this._bullets = [];

        //包围盒
        this.boxCollider = new BoxCollider2D({
            min: vec3.fromValues(-1, -1, 0),
            max: vec3.fromValues(1, 1, 0)
        });

        this._tmpPoint = vec3.create();
        this._tmpMatrix = mat4.create();
        this.addEventListener("applyDamage", this.acceptDamage);
        this.initEvent();
    }

    acceptDamage() {
        databus.gameOver = true;
    }

    //更新事件
    onUpdate(timestamp, frameDelta) {
        if (databus.gameOver) return;

        this._time += frameDelta;

        if (this._time > this.fireCooldown) {
            this._time %= this.fireCooldown;

            //发射子弹
            if (this.parent != null) {
                let bullet = null;
                let x = this.translation[0];
                let y = this.translation[1] + this.scale[1] + 0.01;
                let z = 0.0;

                if (this._bullets.length > 0) {
                    bullet = this._bullets.shift();
                    bullet.reset(x, y, z);
                }
                else {
                    bullet = new Bullet(x, y, z);

                    let that = this;

                    bullet.addEventListener("recover", function () {
                        that._bullets.push(this);
                    });

                    this.parent.add(bullet);
                }

                music.playShoot();
            }
        }
    }

    //手指拖动事件
    initEvent() {
        canvas.addEventListener('touchstart', ((e) => {
            const x = e.touches[0].clientX;
            const y = e.touches[0].clientY;

            if (this.checkIsFingerOnAir(x, y)) {
                this.touched = true

                this.setAirPosAcrossFingerPosZ(x, y)
            }
        }));

        canvas.addEventListener('touchmove', ((e) => {
            const x = e.touches[0].clientX;
            const y = e.touches[0].clientY;

            if (this.touched) this.setAirPosAcrossFingerPosZ(x, y)
        }));

        canvas.addEventListener('touchend', ((e) => {
            this.touched = false
        }));
    }

    checkIsFingerOnAir(x, y) {
        let point = this._tmpPoint;
        let worldMatrixInvert = this._tmpMatrix;

        vec3.set(point, x, y, 0);

        databus.mainCamera.unproject(point, point, canvas.width, canvas.height);

        mat4.invert(worldMatrixInvert, this.worldMatrix);
        vec3.transformMat4(point, point, worldMatrixInvert);

        return point[0] >= this.boxCollider.min[0]
            && point[1] >= this.boxCollider.min[1]
            && point[0] <= this.boxCollider.max[0]
            && point[1] <= this.boxCollider.max[1];
    }

    setAirPosAcrossFingerPosZ(x, y) {
        if (databus.gameOver) return;

        let point = this._tmpPoint;

        vec3.set(point, x, y, 0);

        databus.mainCamera.unproject(point, point, canvas.width, canvas.height);

        if (point[0] < this._minX) {
            point[0] = this._minX;
        }
        else if (point[0] > this._maxX) {
            point[0] = this._maxX;
        }

        if (point[1] < this._minY) {
            point[1] = this._minY;
        }
        else if (point[1] > this._maxY) {
            point[1] = this._maxY;
        }

        point[2] = this.translation[2];

        vec3.copy(this.translation, point);
    }
}